package game.worlds;

import hx.geom.Point;

/**
 * 抖动管理器
 */
class ShakeManager {
	/**
	 * 震动数组
	 */
	public var shakes:Array<AdvancedShake> = [];

	public function new() {}

	public var point:Point = new Point();

	public function update(dt:Float):Point {
		point.x = point.y = 0;
		var i = shakes.length;
		while (i-- > 0) {
			var shake = shakes[i];
			shake.update(dt);
			point.x += shake.offsetX;
			point.y += shake.offsetY;
			// 要限制范围在-100,100之间
			shake.offsetX = limit(shake.offsetX, -100, 100);
			shake.offsetY = limit(shake.offsetY, -100, 100);
			if (shake.timer <= 0) {
				shakes.splice(i, 1);
			}
		}
		return point;
	}

	public function limit(value:Float, min:Float, max:Float):Float {
		if (value < min)
			return min;
		if (value > max)
			return max;
		return value;
	}

	/**
	 * 发起震动
	 * @param intensity 震动强度
	 * @param duration 震动时长
	 */
	public function addShake(intensity:Float, duration:Float, frequency:Float = 10):Void {
		var shake = new AdvancedShake();
		shake.start(intensity, duration, frequency);
		shakes.push(shake);
	}
}

/**
 * 震动单个例子
 */
class AdvancedShake {
	public var offsetX:Float = 0;
	public var offsetY:Float = 0;

	private var intensity:Float;
	private var duration:Float;

	public var timer:Float;

	private var frequency:Float; // 震动频率
	private var falloffCurve:Float->Float; // 衰减曲线函数

	public function new() {
		// 默认使用二次衰减曲线
		falloffCurve = function(t:Float):Float {
			// return t * t;
			return t;
		};
	}

	public function start(intensity:Float, duration:Float, frequency:Float = 10):Void {
		this.intensity = intensity;
		this.duration = duration;
		this.timer = duration;
		this.frequency = frequency;
	}

	public function update(deltaTime:Float):Void {
		if (timer <= 0) {
			offsetX = 0;
			offsetY = 0;
			return;
		}

		timer -= deltaTime;
		var progress = timer / duration;
		var currentIntensity = intensity * falloffCurve(1 - progress);

		// 使用Perlin噪声或正弦波创建更自然的震动
		var time = (duration - timer) * frequency;
		// offsetX = Math.sin(time * 1.7) * currentIntensity;
		// offsetY = Math.sin(time * 2.3) * currentIntensity;
		offsetX = Math.sin(time * 2) * currentIntensity;
		offsetY = Math.cos(time * 2) * currentIntensity;
	}

	// 设置自定义衰减曲线
	public function setFalloffCurve(curve:Float->Float):Void {
		this.falloffCurve = curve;
	}
}
